namespace Yaaf.WP7.NativeAccess.IO
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Threading;

    using Yaaf.WP7.NativeAccess.Helper;

    public class Directory
    {
        public static void Delete(string path, bool recursive = false)
        {
            path = Normalize(path);
            FileSystemAccess.DeleteDirectory(path, recursive);
        }

        public static bool Exists(string path)
        {
            path = Normalize(path);
            return FileSystemAccess.ExistsDirectory(path);
        }

        public static IEnumerable<FileSystemEntryStruct> GetFileSystemEntries(string path, string search = null, bool fullPath = true)
        {
            path = Normalize(path);
            return EnumerateEntries(path, true, true, search, fullPath);
        }

        public static IEnumerable<string> GetFiles(string path, string search = null, bool fullPath = true)
        {
            path = Normalize(path);
            return EnumerateEntries(path, true, false, search, fullPath).Select(s => s.Name);
        }
        public static IEnumerable<string> GetDirectories(string path, string search = null, bool fullPath = true)
        {
            path = Normalize(path);
            return EnumerateEntries(path, false, true, search, fullPath).Select(s => s.Name);
        }

        private static IEnumerable<FileSystemEntryStruct> EnumerateEntries(string path, bool includeFiles, bool includeDirectories, string search = null, bool fullPath = true)
        {
            path = Normalize(path);
            return FileSystemAccess.EnumerateFileSystemEntries(path, includeFiles, includeDirectories, search, fullPath);
        }

        public static void Create(string fullName)
        {
            fullName = Normalize(fullName);
            FileSystemAccess.CreateDirectory(fullName);
        }

        private static string Normalize(string path)
        {
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }

            if (path.EndsWith("\\") && path.Length > 1)
            {
                path = path.Substring(0, path.Length - 1);
            }

            if (path == "")
            {
                return "\\";
            }

            return path;
        }

        private static void CopyToPrivate(string source, string dest, bool overwrite)
        {
            source = Normalize(source);
            dest = Normalize(dest);

            if (!Directory.Exists(dest))
            {
                Directory.Create(dest);
            }
            
            foreach (var subElem in GetFileSystemEntries(source, fullPath: false))
            {
                var sourcePath = Path.Combine(source, subElem.Name);
                var destPath = Path.Combine(dest, subElem.Name);

                bool isFile = subElem.IsFile.HasValue 
                    ? subElem.IsFile.Value 
                    : File.Exists(sourcePath);
                if (isFile)
                {
                    if (overwrite || !File.Exists(destPath))
                    {
                        File.Copy(sourcePath, destPath, overwrite);
                    }
                }
                else
                {
                    CopyToPrivate(sourcePath, destPath, overwrite);
                }
            }
        }

        public static void CopyTo(string sourceDir, string targetDir, string newName, bool overwrite = false)
        {
            sourceDir = Normalize(sourceDir);
            targetDir = Normalize(targetDir);
            newName = string.IsNullOrEmpty(newName) ? Path.GetFileName(sourceDir) : newName;
            var currentTarget = Path.Combine(targetDir, newName);
            CopyToPrivate(sourceDir, currentTarget, overwrite);
        }
    }

}